pub mod request;
pub mod response;

use crate::component::request::Request;
use crate::component::response::Response;
use futures::future;
use std::sync::Arc;

pub struct ParseResult<M, ItemType> {
    pub tasks: Vec<Task<M, ItemType>>,
    pub items: Vec<ItemType>,
}

impl<M, ItemType> ParseResult<M, ItemType> {
    pub fn new(tasks: Vec<Task<M, ItemType>>, items: Vec<ItemType>) -> Self {
        Self { tasks, items }
    }
}

pub trait AsyncFn<ItemType, M>: Send + Sync {
    fn call(
        &self,
        resp: Response,
        meta: Option<M>,
    ) -> future::BoxFuture<'static, ParseResult<M, ItemType>>;
}

impl<T, F, ItemType, M> AsyncFn<ItemType, M> for T
where
    T: Send + Sync + Fn(Response, Option<M>) -> F,
    F: future::Future<Output = ParseResult<M, ItemType>> + 'static + Send + Sync,
    ItemType: Send + Sync + Clone,
    M: Send + Sync + Clone,
{
    fn call(
        &self,
        resp: Response,
        metadata: Option<M>,
    ) -> future::BoxFuture<'static, ParseResult<M, ItemType>> {
        Box::pin(self(resp, metadata))
    }
}

pub struct Task<M, ItemType> {
    pub req: Request,
    pub meta: Option<M>,
    pub parser: Option<Arc<dyn AsyncFn<ItemType, M>>>,
}
